package org.idea.qiyu.framework.jmh.demo;

import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.annotations.Benchmark;

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.*;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

/**
 * @Author linhao
 * @Date created in 7:04 下午 2021/12/14
 */
/**
 * 吞吐量测试 可以获取到指定时间内的吞吐量
 *
 * Throughput 可以获取一秒内可以执行多少次调用
 * AverageTime 可以获取每次调用所消耗的平均时间
 * SampleTime 随机抽样，随机抽取结果的分布，最终是99%%的请求在xx秒内
 * SingleShotTime 只允许一次，一般用于测试冷启动的性能
 */
@BenchmarkMode(Mode.Throughput)
/**
 * 如果一段程序被调用了好几次，那么机器就会对其进行预热操作，
 * 为什么需要预热？因为 JVM 的 JIT 机制的存在，如果某个函数被调用多次之后，JVM 会尝试将其编译成为机器码从而提高执行速度。所以为了让 benchmark 的结果更加接近真实情况就需要进行预热。
 */
@Warmup(iterations = 3)
/**
 * iterations 每次测试的轮次
 * time 每轮进行的时间长度
 * timeUnit 时长单位
 */
@Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS)
/**
 * 测试的线程数，一般是cpu*2
 */
@Threads(8)
/**
 * fork多少个进程出来测试
 */
@Fork(2)
/**
 * 这个比较简单了，基准测试结果的时间类型。一般选择秒、毫秒、微秒。
 */
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class StringBuilderBenchmark {


    /**
     * 表示什么方法需要进行压力测试
     */
    @Benchmark
    public void testStringAdd() {
        String a = "";
        for (int i = 0; i < 10; i++) {
            a += i;
        }
        // System.out.println(a);
    }


    @Benchmark
    public void testStringBuilderAdd() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(i);
        }
        // System.out.println(sb.toString());
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(StringBuilderBenchmark.class.getSimpleName())
                .output("/Users/linhao/IdeaProjects/qiyu-framework-gitee/qiyu-framework/qiyu-framework-jmh/log/test.log")
                .build();
        new Runner(options).run();
    }

}
